#include "systemInfo.h"
#include <cstring>
#include <iostream>
void 
SystemInfo::setGeneral(UINT8 len, const std::string &manufacturer, const std::string &productName,
                       const std::string &version, const std::string &serialNumber)
{
    _length = len;
    _manufacturer = manufacturer;
    _productName = productName;
    _version = version;
    _serialNumber = serialNumber;
}
void 
SystemInfo::setUUID(const UINT8 *uuid)
{
    memcpy(_UUID, uuid, 16);
}

void 
SystemInfo::print()
{
    if (_length < 0x08)
        return;
    std::cout << "System Information:" << std::endl;
    std::cout << "\tManufacturer: " << _manufacturer << std::endl;
    std::cout << "\tProduct Name: " << _productName << std::endl;
    std::cout << "\tVersion: " << _version << std::endl;
    std::cout << "\tSerial Number: " << _serialNumber << std::endl;
    
    if (_length < 0x19)
        return;
    printSystemUUID();
    std::cout << "\tWake-up Type: " << printSystemWakeUpType() << std::endl;

    std::cout << "\tSKU Number: " << _skuNumber << std::endl;
    std::cout << "\tFamily: " << _family << std::endl;
}

void 
SystemInfo::printSystemUUID()
{
	int only0xFF = 1, only0x00 = 1;

	for (int i = 0; i < 16 && (only0x00 || only0xFF); i++) {
		if (_UUID[i] != 0x00) only0x00 = 0;
		if (_UUID[i] != 0xFF) only0xFF = 0;
	}

    std::cout << "\tUUID: ";

    if (only0xFF) {
		std::cout << "Not Present" << std::endl;
        return;
    }
    if (only0x00) {
		std::cout << "Not Settable\n" << std::endl;
		return;
	}

	/*
	 * As of version 2.6 of the SMBIOS specification, the first 3
	 * fields of the UUID are supposed to be encoded on little-endian.
	 * The specification says that this is the defacto standard,
	 * however I've seen systems following RFC 4122 instead and use
	 * network byte order, so I am reluctant to apply the byte-swapping
	 * for older versions.
	 */
	if (_smbiosVersion >= 0x0206) {
        printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
               _UUID[3], _UUID[2], _UUID[1], _UUID[0], _UUID[5], _UUID[4],_UUID[7], _UUID[6],
               _UUID[8], _UUID[9], _UUID[10], _UUID[11], _UUID[12], _UUID[13], _UUID[14], _UUID[15]);
    } else {
        printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
               _UUID[0], _UUID[1], _UUID[2], _UUID[3], _UUID[4], _UUID[5], _UUID[6], _UUID[7],
               _UUID[8], _UUID[9], _UUID[10], _UUID[11], _UUID[12], _UUID[13], _UUID[14], _UUID[15]);
    }
}

const char *
SystemInfo::printSystemWakeUpType()
{
	/* 7.2.2 */
	static const char *type[] = {
		"Reserved", /* 0x00 */
		"Other",
		"Unknown",
		"APM Timer",
		"Modem Ring",
		"LAN Remote",
		"Power Switch",
		"PCI PME#",
		"AC Power Restored" /* 0x08 */
	};

	if (_wakeupType <= 0x08)
		return type[_wakeupType];
	return OUT_OF_SPEC;
}
